#pragma once
#include <iostream>
#include <vector>
#include "Sem.hpp"
#include "../Mutex/Mutex.hpp"

static const int gcap = 5; // for test

using namespace SemModule;
using namespace MutexModule;

template<class T>
class RingQueue {
public:
    RingQueue(int cap = gcap) 
    : _cap(cap), _rq(cap), _blank_sem(cap), _p_step(0), _data_sem(0), _c_step(0)
    {}

    // 入队操作 --- 生产者
    void Equeue(const T& in) {
        _blank_sem.P();
        {
            LockGuard lockGuard(_pmutex);
            _rq[_p_step] = in;
            ++_p_step; _p_step %= _cap;
        }
        _data_sem.V();
    }

    // 出队操作 --- 消费者
    void Pop(T* out) {
        _data_sem.P();
        {
            LockGuard lockGuard(_cmutex);
            *out = _rq[_c_step];
            ++_c_step; _c_step %= _cap;
        }
        _blank_sem.V();
    }
private:
    std::vector<T> _rq;
    int _cap;
    // 生产相关
    Sem _blank_sem;
    int _p_step;
    Mutex _pmutex;
    // 消费者小关
    Sem _data_sem;
    int _c_step;
    Mutex _cmutex;
};